package com.alks.function.service.impl.web.statements;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.merge.LoopMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.fastjson2.JSON;
import com.alks.common.service.RedisService;
import com.alks.common.utils.DateUtils;
import com.alks.common.utils.excelUtils.CustomMergeStrategy;
import com.alks.common.utils.excelUtils.ExcelUtils;
import com.alks.common.utils.stringUtils.ZStringUtils;
import com.alks.entity.data.entity.*;
import com.alks.entity.data.entity.stitch.StitchMonthVo;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.function.data.dto.develop.DevelopBrand;
import com.alks.function.data.dto.develop.DevelopDelivery;
import com.alks.function.data.dto.finance.statement.DhReceiptDetailDto;
import com.alks.function.data.dto.finance.statement.DhReceiptDto;
import com.alks.function.data.request.prod.ProdDayDetail;
import com.alks.function.mapper.web.statements.StatementsMapper;
import com.alks.function.service.web.statements.StatementsService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.alks.common.utils.excelUtils.ExcelUtilBuild.ExcelNameException;

/**
 * @author:hxl
 * @create: 2024-11-28 14:43
 * @Description:
 */
@Service
public class StatementsServiceImpl implements StatementsService {
    @Autowired
    StatementsMapper statementsMapper;

    @Autowired
    private RedisService redisService;

    @Override
    public ResponseInfo dHFinanceCreditDetail(String invoiceNo, Date startDate, Date endDate, Integer pageNum, Integer pageSize) {
        Map<String, Object> map = new HashMap<>();
        PageHelper.startPage(pageNum, pageSize);
        List<StatementsInvoice> list = statementsMapper.dHFinanceCreditDetail(invoiceNo, startDate, endDate);
        map.put("list", list);
        map.put("total", new PageInfo<>(list).getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public void downloadDhFinanceCreditDetail(HttpServletResponse response, StatementsInvoice result) throws IOException {
        List<DhFinanceCreditDetail> list = statementsMapper.downloadDhFinanceCreditDetail(result);
        List<List<String>> mergeColDataList = Stream.of(list.stream().map(x -> x.getOrderType()).collect(Collectors.toList()),
                list.stream().map(x -> x.getCreditNo()).collect(Collectors.toList())).collect(Collectors.toList());
        List<Integer> mergeColIndexList = Stream.of(0, 1).collect(Collectors.toList());
        ExcelUtils.creatByTemplateM(response, "dh_finance_credit_detail_d.xlsx", "dh_finance_credit_detail_d.xlsx", list, mergeColDataList, mergeColIndexList);
//        EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(list);
    }

    @Override
    public ResponseInfo getDhFinanceDetail(StatementsInvoice result) {
        List<DhFinanceCreditDetail> list = statementsMapper.downloadDhFinanceCreditDetail(result);
        return ResponseInfo.ok(list);
    }

    @Override
    public ResponseInfo getStitchMonthProd(String month, String prodSeq) {
        if (!"3".equals(prodSeq) && !"10".equals(prodSeq)) return ResponseInfo.error("prodSeq传参有误");
        Map<String, Object> map = new HashMap<>();
        List<StitchMonthVo> list = statementsMapper.getStitchMonthProd(month, prodSeq);
        Map<String, Object> stitch = statementsMapper.getStitchMonthProdTotal(month, prodSeq);
        stitch = stitch == null ? new HashMap<>() : stitch;
        BigDecimal zQty = statementsMapper.getZqty(month, prodSeq);
        zQty = zQty == null ? new BigDecimal(0) : zQty;
        BigDecimal dQty = statementsMapper.getDqty(month, prodSeq);
        dQty = dQty == null ? new BigDecimal(0) : dQty;
        BigDecimal sQty = statementsMapper.getSqty(month, prodSeq);
        sQty = sQty == null ? new BigDecimal(0) : sQty;
        BigDecimal total = zQty.add(dQty).add(sQty);
        stitch.put("total", total.stripTrailingZeros().toPlainString());
        stitch.put("zQty", zQty.stripTrailingZeros().toPlainString());
        stitch.put("dQty", dQty.stripTrailingZeros().toPlainString());
        stitch.put("sQty", sQty.stripTrailingZeros().toPlainString());
        map.put("list", list);
        map.put("stitch", stitch);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo getCurrentMonth(String workerId, String month, String choose, String prodStep) {
        List<CutYield> list = statementsMapper.getCurrentMonth(workerId, month, choose, prodStep);
        return ResponseInfo.ok(list);
    }

    @Override
    public ResponseInfo getOtherMonthProd(String month, String prodSeq) {
        Map<String, Object> map = new HashMap<>();
        List<StitchMonthVo> list = statementsMapper.getOtherMonthProd(month, prodSeq);
        BigDecimal zQty = statementsMapper.getZqty(month, prodSeq);
        map.put("list", list);
        map.put("total", new PageInfo<>(list).getTotal());
        map.put("zQty", zQty);
        return ResponseInfo.ok(map);
    }


    @Override
    public ResponseInfo prodMonthProd(String month) {
        Date date = new Date();
        String redisKey = new SimpleDateFormat("yyyyMMdd").format(date);
        Set scan = redisService.scan(redisKey);
        if (scan.size() > 0) {
            String string = redisService.get(redisKey);
            List list = JSON.parseObject(string, List.class);
            return ResponseInfo.ok(list);
        }
        List<Map<String, Object>> list = new ArrayList<>();
        for (int i = 1; i <= 12; i++) {
            String str = new String(month);
            str = str + String.format("%02d", i);
            Map<String, Object> monthMap = new HashMap<>();
            List<Map<String, Object>> map = statementsMapper.prodMonthProd(str);
            monthMap.put("month", str);
            monthMap.put("list", map);
            list.add(monthMap);
        }
        redisService.set(redisKey, JSON.toJSONString(list));
        return ResponseInfo.ok(list);
    }

    @Override
    public ResponseInfo prodMonthProdDetail(String month, String prodSeq) {
        Calendar instance = Calendar.getInstance();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        List<Map<String, Object>> lists = new ArrayList<>();
        List<String> list = new ArrayList<>();
        try {
            Date parse = format.parse(month);
            String str;
            instance.setTime(parse);
            int maximum = instance.getActualMaximum(Calendar.DAY_OF_MONTH);
            for (int i = 1; i <= maximum; i++) {
                str = month + "-" + String.format("%02d", i);
                list.add(str);
            }
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        if ("1".equals(prodSeq)) {
            for (String string : list) {
                Map<String, Object> stitchMonthVos = statementsMapper.prodMonthProdDetail(string, prodSeq);
                lists.add(stitchMonthVos);
            }
        } else {
            for (String string : list) {
                Map<String, Object> stitchMonth = statementsMapper.prodMonthProdDetail1(string, prodSeq);
                lists.add(stitchMonth);
            }
        }
        return ResponseInfo.ok(lists);
    }

    @Override
    public ResponseInfo prodDayProd(Date startDate, Date endDate, String prodSeq) {
        List<String> lDate = new ArrayList<>();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar start = Calendar.getInstance();
        start.setTime(startDate);
        lDate.add(format.format(startDate));
        Calendar end = Calendar.getInstance();
        end.setTime(endDate);
        while (end.after(start)) {
            start.add(Calendar.DAY_OF_MONTH, 1);
            lDate.add(format.format(start.getTime()));
        }
        //板房单独放一个，其他都用这一个
        List<ProdDayDetail> lists = new ArrayList<>();
        for (String string : lDate) {
            List<ProdDayDetail> list = statementsMapper.prodDayProd(string, prodSeq);
            lists.addAll(list);
        }
        return ResponseInfo.ok(lists);
    }

    @Override
    public ResponseInfo prodDayProdByYear(String year) {
        Map<String, Object> maps = new HashMap<>();
        BigDecimal tTotal = new BigDecimal(0);
        BigDecimal cTotal = new BigDecimal(0);
        BigDecimal ucTotal = new BigDecimal(0);
        BigDecimal bfTotal = new BigDecimal(0);
        BigDecimal blTotal = new BigDecimal(0);
        BigDecimal cdTotal = new BigDecimal(0);
        BigDecimal ptTotal = new BigDecimal(0);
        BigDecimal zcTotal = new BigDecimal(0);
        BigDecimal cxTotal = new BigDecimal(0);
        List<DevelopDelivery> list = statementsMapper.prodDayProdByYear(year);
        for (DevelopDelivery developDelivery : list) {
            tTotal = tTotal.add(developDelivery.getTQty() == null ? new BigDecimal(0) : developDelivery.getTQty());
            cTotal = cTotal.add(developDelivery.getComQty() == null ? new BigDecimal(0) : developDelivery.getComQty());
            ucTotal = ucTotal.add(developDelivery.getUnComQty() == null ? new BigDecimal(0) : developDelivery.getUnComQty());
            bfTotal = bfTotal.add(developDelivery.getUnBfQty() == null ? new BigDecimal(0) : developDelivery.getUnBfQty());
            blTotal = blTotal.add(developDelivery.getUnBlQty() == null ? new BigDecimal(0) : developDelivery.getUnBlQty());
            cdTotal = cdTotal.add(developDelivery.getUnCdQty() == null ? new BigDecimal(0) : developDelivery.getUnCdQty());
            ptTotal = ptTotal.add(developDelivery.getUnPtQty() == null ? new BigDecimal(0) : developDelivery.getUnPtQty());
            zcTotal = zcTotal.add(developDelivery.getUnZcQty() == null ? new BigDecimal(0) : developDelivery.getUnZcQty());
            cxTotal = cxTotal.add(developDelivery.getUnCxQty() == null ? new BigDecimal(0) : developDelivery.getUnCxQty());
        }
        maps.put("tTotal", tTotal);
        maps.put("cTotal", cTotal);
        maps.put("ucTotal", ucTotal);
        maps.put("bfTotal", bfTotal);
        maps.put("blTotal", blTotal);
        maps.put("cdTotal", cdTotal);
        maps.put("ptTotal", ptTotal);
        maps.put("zcTotal", zcTotal);
        maps.put("cxTotal", cxTotal);
        maps.put("list", list);
        return ResponseInfo.ok(maps);
    }

    @Override
    public ResponseInfo prodDayProdByBrand(String month) {
        Map<String, Object> maps = new HashMap<>();
        BigDecimal tTotal = new BigDecimal(0);
        BigDecimal cTotal = new BigDecimal(0);
        BigDecimal ucTotal = new BigDecimal(0);
        BigDecimal bfTotal = new BigDecimal(0);
        BigDecimal blTotal = new BigDecimal(0);
        BigDecimal cdTotal = new BigDecimal(0);
        BigDecimal ptTotal = new BigDecimal(0);
        BigDecimal zcTotal = new BigDecimal(0);
        BigDecimal cxTotal = new BigDecimal(0);
        List<DevelopDelivery> list;
        if (month.length() == 4) {
            list = statementsMapper.prodDayProdByBrands(month);
        } else {
            list = statementsMapper.prodDayProdByBrand(month);
        }
        for (DevelopDelivery developDelivery : list) {
            tTotal = tTotal.add(developDelivery.getTQty() == null ? new BigDecimal(0) : developDelivery.getTQty());
            cTotal = cTotal.add(developDelivery.getComQty() == null ? new BigDecimal(0) : developDelivery.getComQty());
            ucTotal = ucTotal.add(developDelivery.getUnComQty() == null ? new BigDecimal(0) : developDelivery.getUnComQty());
            bfTotal = bfTotal.add(developDelivery.getUnBfQty() == null ? new BigDecimal(0) : developDelivery.getUnBfQty());
            blTotal = blTotal.add(developDelivery.getUnBlQty() == null ? new BigDecimal(0) : developDelivery.getUnBlQty());
            cdTotal = cdTotal.add(developDelivery.getUnCdQty() == null ? new BigDecimal(0) : developDelivery.getUnCdQty());
            ptTotal = ptTotal.add(developDelivery.getUnPtQty() == null ? new BigDecimal(0) : developDelivery.getUnPtQty());
            zcTotal = zcTotal.add(developDelivery.getUnZcQty() == null ? new BigDecimal(0) : developDelivery.getUnZcQty());
            cxTotal = cxTotal.add(developDelivery.getUnCxQty() == null ? new BigDecimal(0) : developDelivery.getUnCxQty());
        }
        maps.put("tTotal", tTotal);
        maps.put("cTotal", cTotal);
        maps.put("ucTotal", ucTotal);
        maps.put("bfTotal", bfTotal);
        maps.put("blTotal", blTotal);
        maps.put("cdTotal", cdTotal);
        maps.put("ptTotal", ptTotal);
        maps.put("zcTotal", zcTotal);
        maps.put("cxTotal", cxTotal);
        maps.put("list", list);
        return ResponseInfo.ok(maps);
    }

    @Override
    public ResponseInfo prodDayProdByBrandDetail(String month, String prodSeq) {
        List<DevelopBrand> list = statementsMapper.prodDayProdByBrandDetail(month, prodSeq);
        return ResponseInfo.ok(list);
    }

    @Override
    public ResponseInfo getDhReceiptHead(String receiptNo, Date startTime, Date endTime, String custom, Integer pageNum, Integer pageSize) {
        Map<String, Object> map = new HashMap<>();
        PageHelper.startPage(pageNum, pageSize);
        List<DhReceiptDto> list = statementsMapper.getDhReceiptHead(receiptNo, startTime, endTime, custom);
        BigDecimal amt = statementsMapper.getDhReceiptHeadAmt(receiptNo, startTime, endTime, custom);
        map.put("list", list);
        map.put("total", new PageInfo<>(list).getTotal());
        map.put("amt", amt);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo getDhReceiptDetail(String receiptNo) {
        List<DhReceiptDetailDto> list = statementsMapper.getDhReceiptDetail(receiptNo);
        Map<String, Object> map = statementsMapper.getDhReceiptDetailAmt(receiptNo);
        map.put("list", list);
        return ResponseInfo.ok(map);
    }

    @Override
    public void downloadDhReceiptHead(HttpServletResponse response, String receiptNo, Date startTime, Date endTime, String custom) throws IOException {
        Map<String, Object> map = new HashMap<>();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        List<DhReceiptDto> list = statementsMapper.getDhReceiptHead(receiptNo, startTime, endTime, custom);
        for (DhReceiptDto dhReceiptDto : list) {
            dhReceiptDto.setRecTime(dhReceiptDto.getRecDate() != null ? format.format(dhReceiptDto.getRecDate()) : "");
        }
        BigDecimal amt = statementsMapper.getDhReceiptHeadAmt(receiptNo, startTime, endTime, custom);
        map.put("amt", amt);
        ExcelUtils.creatByTemplate(response, "dh_finance_ar_detail.xlsx", "dh_finance_ar_detail", list, map);
    }

    @Override
    public void downloadDhReceiptDetail(HttpServletResponse response, String receiptNo) throws IOException {
        List<DhReceiptDetailDto> list = statementsMapper.getDhReceiptDetail(receiptNo);
        Map<String, Object> map = statementsMapper.getDhReceiptDetailAmt(receiptNo);
        ExcelUtils.creatByTemplate(response, "dh_finance_ar_detail_d.xlsx", "dh_finance_ar_detail_d", list, map);
    }

    @Override
    public ResponseInfo analysisByBrand(String brand) {
        Map<String, Object> map = new HashMap<>();
        List<String> seasons = statementsMapper.getSeasonByBrand(brand);
        for (String season : seasons) {
            Map<String, Object> sMap = new HashMap<>();
            sMap.put("season", season);
            List<DevelopDelivery> list = statementsMapper.analysisByBrand(brand, season);
            sMap.put("list", list);
            map.put(season, sMap);
        }
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo getUnfinishedByBrand(String brand, String season, String prodSeq, String month) {
        List<DevelopBrand> list = statementsMapper.getUnfinishedByBrand(brand, season, prodSeq, month);
        return ResponseInfo.ok(list);
    }

    @Override
    public ResponseInfo getCompletedByMonth(Date startDate, Date endDate) {
        List<YpProdTotal> list = statementsMapper.getCompletedByMonth(startDate, endDate);
        for (YpProdTotal ypProdTotal : list) {
            BigDecimal schProd = ypProdTotal.getSchProd() == null ? BigDecimal.ZERO : ypProdTotal.getSchProd();
            BigDecimal planQty = ypProdTotal.getPlanQty();
            BigDecimal divide = schProd.divide(planQty, BigDecimal.ROUND_HALF_UP, 4);
            ypProdTotal.setRate(divide);
        }
        return ResponseInfo.ok(list);
    }

    @Override
    public ResponseInfo getWeekPlan(Date startDate, Date endDate, String choose, Integer pageNum, Integer pageSize) {
        Map<String, Object> map = new HashMap<>();
        List<Map> list = new ArrayList<>();
        PageHelper.startPage(pageNum, pageSize);
        switch (choose) {
            case "1":
                list = statementsMapper.getWeekPlan1(startDate, endDate);
                break;
            case "2":
                list = statementsMapper.getWeekPlan2(startDate, endDate);
                break;
            case "3":
                list = statementsMapper.getWeekPlan3(startDate, endDate);
                break;
            case "4":
                list = statementsMapper.getWeekPlan7(startDate, endDate);
                break;
            case "5":
                list = statementsMapper.getWeekPlan4(startDate, endDate);
                break;
            case "6":
                list = statementsMapper.getWeekPlan5(startDate, endDate);
                break;
            case "7":
                list = statementsMapper.getWeekPlan6(startDate, endDate);
                break;
        }
        map.put("list", list);
        map.put("total", new PageInfo(list).getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo getDayPlan(Date day, String choose) {
        Map map = new HashMap<>();
        List<YpPlanDay> list = new ArrayList<>();
        List<YpPlanDayDelay> delayList = new ArrayList<>();
        switch (choose) {
            case "1":
                list = statementsMapper.getDayPlan1(day);
                delayList = statementsMapper.getDayPlanDelay1(day);
                break;
            case "2":
                list = statementsMapper.getDayPlan2(day);
                delayList = statementsMapper.getDayPlanDelay2(day);
                break;
            case "3":
                list = statementsMapper.getDayPlan3(day);
                delayList = statementsMapper.getDayPlanDelay3(day);
                break;
            case "4":
                list = statementsMapper.getDayPlan4(day);
                delayList = statementsMapper.getDayPlanDelay4(day);
                break;
            case "5":
                list = statementsMapper.getDayPlan5(day);
                delayList = statementsMapper.getDayPlanDelay5(day);
                break;
            case "6":
                list = statementsMapper.getDayPlan6(day);
                delayList = statementsMapper.getDayPlanDelay6(day);
                break;
            case "7":
                list = statementsMapper.getDayPlan7(day);
                delayList = statementsMapper.getDayPlanDelay7(day);
                break;
        }

        map.put("list", list);
        map.put("delayList", delayList);
        return ResponseInfo.ok(map);
    }
}
